package com.ws.demo.allTheDisappearNumber;

import com.alibaba.fastjson.JSONObject;

import java.util.*;

public class AllTheDisappearNumberDemo {

    /**
     * 给你一个含 n 个整数的数组 nums ，其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字，并以数组的形式返回结果。
     */
//    public static List<Integer> findDisappearedNumbers(int[] nums) {
//        Arrays.sort(nums);
//        List<Integer> list = new ArrayList<>();
//        int n = 1;
//        for (int i = 0; i < nums.length; i++) {
//            //已排序 根据当前元素与指针的差算出有多少空隙
//            if (nums[i] > n && (i == 0 || nums[i] != nums[i-1])) {
//                for (int j = n; j < nums[i]; j++) {
//                    list.add(j);
//                }
//            }
//            n = nums[i] + 1;
//        }
//        for (int i = n; i < nums.length+1; i++) {
//            list.add(i);
//        }
//        return list;
//    }

    /**
     * 由于 nums 的数字范围均在 [1,n] 中，我们可以利用这一范围之外的数字，来表达「是否存在」的含义。
     * 具体来说，遍历 nums，每遇到一个数 xx，就让 nums[x−1] 增加 nn。由于 nums 中所有数均在 [1,n] 中，
     * 增加以后，这些数必然大于 n。最后我们遍历 nums，若 nums[i] 未大于 n，就说明没有遇到过数 i+1。这样我们就找到了缺失的数字。
     *
     * 注意，当我们遍历到某个位置时，其中的数可能已经被增加过，因此需要对 nn 取模来还原出它本来的值。
     */
    public static List<Integer> findDisappearedNumbers(int[] nums) {
        int n = nums.length;
        for (int num : nums) {
            int x = (num - 1) % n;
            nums[x] += n;
        }
        List<Integer> ret = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if (nums[i] <= n) {
                ret.add(i + 1);
            }
        }
        return ret;
    }


    public static void main(String[] args) {
        int[] ints = {1,1,1,5,5};
        System.out.println(JSONObject.toJSONString(findDisappearedNumbers(ints)));
    }
}
